package com.my.security.component;

import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

/**
 * @author zhupanlin
 * @version 1.0
 * @description: TODO
 * @date 2024/2/24 14:16
 */
@Component // 来定义如何去数据库中按照用户名查询用户
public class AppReactiveUserDetailService implements ReactiveUserDetailsService {
    
    
    @Resource 
    DatabaseClient databaseClient;
    @Autowired
    PasswordEncoder passwordEncoder;
    
    // 自定义如何按照用户名去数据库查询用户信息
    @Override
    public Mono<UserDetails> findByUsername(String username) {

        Mono<UserDetails> userDetailsMono = databaseClient.sql("select u.*, r.id rid, r.name, r.value, pm.id pid, pm.value, pm.description from t_user u\n" +
                        "left join t_user_role ur on ur.user_id = u.id\n" +
                        "left join t_roles r on r.id = ur.role_id\n" +
                        "left join t_role_perm rp on rp.role_id = r.id\n" +
                        "left join t_perm pm on rp.perm_id = pm.id\n" +
                        "where u.username = ? limit 1")
                .bind(0, username)
                .fetch()
                .one()
                .map(map -> {
                    UserDetails build = User.builder()
                            .username(username)
                            .password(map.get("password").toString())
                            //.passwordEncoder(str -> passwordEncoder.encode(str))
                            .authorities("download", "view", "delete") // 权限
                            .roles("admin", "sale")
                            .build();
                    return build;
                });
        
        return userDetailsMono;
    }
}
